package mx.unam.fciencias.actividadesculturales.entidades.portal;

import java.io.Serializable;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.UniqueConstraint;

import mx.unam.fciencias.actividadesculturales.entidades.portal.enums.Rol;
import mx.unam.fciencias.actividadesculturales.entidades.portal.enums.TipoPermiso;
import org.hibernate.annotations.Cascade;

/**
 * Clase que implementa los atributos de la entidad usuariosistema.
 * @author lumartin
 */
@Entity
@Table(schema = "cultura", uniqueConstraints = {
    @UniqueConstraint(columnNames = {
        "username"
    })
})
public class UsuarioSistema implements Serializable {

    @Id
    @SequenceGenerator(name = "usuarioSistema_seq_id",
    sequenceName = "usuarioSistema_seq_id")
    @GeneratedValue(generator = "usuarioSistema_seq_id",
    strategy = GenerationType.AUTO)
    private long id;
    @Column(nullable = false)
    private String username;
    @Column(nullable = false)
    private String passwd;
    private String email;
    @Column(nullable = false)
    private String nombreCompleto;
    private String puesto;
    @Temporal(TemporalType.TIMESTAMP)
    @Column(nullable = false)
    private Date fechaAlta;
    @Column(nullable = false)
    @Enumerated(EnumType.STRING)
    private Rol rolUsuario;
    @Column(nullable = false)
    private boolean usuarioActivo;
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "usuario", fetch = FetchType.EAGER)
    @Column(nullable = false)
    @Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
    private Set<Permiso> permisos = new HashSet<Permiso>();

    public UsuarioSistema() {
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPasswd() {
        return passwd;
    }

    public void setPasswd(String passwd) {
        this.passwd = passwd;
    }

    
    public String getNombreCompleto() {
        return nombreCompleto;
    }

    public void setNombreCompleto(String nombreCompleto) {
        this.nombreCompleto = nombreCompleto;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public Date getFechaAlta() {
        return fechaAlta;
    }

    public void setFechaAlta(Date fechaAlta) {
        this.fechaAlta = fechaAlta;
    }

    public String getPuesto() {
        return puesto;
    }

    public void setPuesto(String puesto) {
        this.puesto = puesto;
    }

    public Rol getRol() {
        return rolUsuario;
    }

    public void setRol(Rol tipoUsuario) {
        this.rolUsuario = tipoUsuario;
    }

    public boolean isUsuarioActivo() {
        return usuarioActivo;
    }

    public void setUsuarioActivo(boolean usuarioActivo) {
        this.usuarioActivo = usuarioActivo;
    }

    public Set<Permiso> getPermisos() {
        return permisos;
    }

    public void setPermisos(Set<Permiso> permisos) {
        this.permisos = permisos;
    }

    /**
     * Indica si el usuario es administrador.
     * @return true si lo es.
     */
    public boolean esAdministrador() {
        return this.rolUsuario != null
                && this.rolUsuario.equals(Rol.ADMINISTRADOR);
    }

    /**
     * Indica si este usuario tiene acceso de lectura de datos.
     * @return true si los tiene.
     */
    public boolean puedeLeer() {
        if (esAdministrador()) {
            return true;
        }
        for (Permiso p : permisos) {
            if (p.getPermiso().equals(TipoPermiso.CONSULTAR)) {
                return true;
            }
        }
        return false;
    }

    /**
     * Indica si este usuario tiene acceso de adición de datos.
     * @return true si los tiene.
     */
    public boolean puedeEscribir() {
        if (esAdministrador()) {
            return true;
        }
        for (Permiso p : permisos) {
            if (p.getPermiso().equals(TipoPermiso.ACTUALIZAR)
                    || p.getPermiso().equals(TipoPermiso.AGREGAR)) {
                return true;
            }
        }
        return false;
    }

    /**
     * Indica si este usuario tiene acceso de eliminación de datos.
     * @return true si los tiene.
     */
    public boolean puedeEliminar() {
        if (esAdministrador()) {
            return true;
        }
        for (Permiso p : permisos) {
            if (p.getPermiso().equals(TipoPermiso.ELIMINAR)) {
                return true;
            }
        }
        return false;
    }

    @Override
    public String toString() {
        return String.format(
                "UsuarioSistema[id: %s, username: %s, nombre: %s, activo: %s]",
                id, username, nombreCompleto, usuarioActivo);
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final UsuarioSistema other = (UsuarioSistema) obj;
        if ((this.username == null) ? (other.username != null) : !this.username.equals(other.username)) {
            return false;
        }
        if (this.fechaAlta != other.fechaAlta && (this.fechaAlta == null || !this.fechaAlta.equals(other.fechaAlta))) {
            return false;
        }
        if (this.id != other.id && (this.id == 0 || this.id != other.id)) {
            return false;
        }
        return true;
    }

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 59 * hash + (this.username != null ? this.username.hashCode() : 0);
        hash = 59 * hash + (this.passwd != null ? this.passwd.hashCode() : 0);
        hash = 59 * hash + (this.email != null ? this.email.hashCode() : 0);
        hash = 59 * hash + (this.nombreCompleto != null ? this.nombreCompleto.hashCode() : 0);
        hash = 59 * hash + (this.puesto != null ? this.puesto.hashCode() : 0);
        hash = 59 * hash + (this.fechaAlta != null ? this.fechaAlta.hashCode() : 0);
        hash = 59 * hash + (this.rolUsuario != null ? this.rolUsuario.hashCode() : 0);
        hash = 59 * hash + (this.usuarioActivo ? 1 : 0);
        return hash;
    }

}
